From a7ec3ba53fb9978cf6bae91816f80ad5f5cf88de Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Thu, 13 Sep 2012 18:11:29 +0200 Subject: [PATCH] csscomputedvalues: Get rid of animated values Merge the animated values code into the computed values code. This should get rid of various bugs related to animated->computed updating. --- gtk/Makefile.am | 2 - gtk/gtkcssanimatedvalues.c | 400 ------------------------------ gtk/gtkcssanimatedvaluesprivate.h | 64 ----- gtk/gtkcsscomputedvalues.c | 306 +++++++++++++++++++++++ gtk/gtkcsscomputedvaluesprivate.h | 25 +- gtk/gtkstylecontext.c | 30 +-- 6 files changed, 336 insertions(+), 491 deletions(-) delete mode 100644 gtk/gtkcssanimatedvalues.c delete mode 100644 gtk/gtkcssanimatedvaluesprivate.h diff --git a/gtk/Makefile.am b/gtk/Makefile.am index bb619a4bd7..9997ccd41a 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -426,7 +426,6 @@ gtk_private_h_sources = \ gtkcolorscaleprivate.h \ gtkcolorchooserprivate.h \ gtkcontainerprivate.h \ - gtkcssanimatedvaluesprivate.h \ gtkcssanimationprivate.h \ gtkcssarrayvalueprivate.h \ gtkcssbgsizevalueprivate.h \ @@ -648,7 +647,6 @@ gtk_base_c_sources = \ gtkcombobox.c \ gtkcomboboxtext.c \ gtkcontainer.c \ - gtkcssanimatedvalues.c \ gtkcssanimation.c \ gtkcssarrayvalue.c \ gtkcssbgsizevalue.c \ diff --git a/gtk/gtkcssanimatedvalues.c b/gtk/gtkcssanimatedvalues.c deleted file mode 100644 index c7f9d0e3bf..0000000000 --- a/gtk/gtkcssanimatedvalues.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright © 2012 Red Hat Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - * - * Authors: Benjamin Otte - */ - -#include "config.h" - -#include "gtkcssanimatedvaluesprivate.h" - -#include "gtkcssanimationprivate.h" -#include "gtkcssarrayvalueprivate.h" -#include "gtkcssenumvalueprivate.h" -#include "gtkcssnumbervalueprivate.h" -#include "gtkcssshorthandpropertyprivate.h" -#include "gtkcssstringvalueprivate.h" -#include "gtkcssstylepropertyprivate.h" -#include "gtkcsstransitionprivate.h" -#include "gtkstyleanimationprivate.h" -#include "gtkstylepropertiesprivate.h" -#include "gtkstylepropertyprivate.h" -#include "gtkstyleproviderprivate.h" - -G_DEFINE_TYPE (GtkCssAnimatedValues, _gtk_css_animated_values, GTK_TYPE_CSS_COMPUTED_VALUES) - -static void -gtk_css_animated_values_dispose (GObject *object) -{ - GtkCssAnimatedValues *values = GTK_CSS_ANIMATED_VALUES (object); - - g_slist_free_full (values->animations, g_object_unref); - values->animations = NULL; - - G_OBJECT_CLASS (_gtk_css_animated_values_parent_class)->dispose (object); -} - -static void -_gtk_css_animated_values_class_init (GtkCssAnimatedValuesClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->dispose = gtk_css_animated_values_dispose; -} - -static void -_gtk_css_animated_values_init (GtkCssAnimatedValues *animated_values) -{ -} - -/* TRANSITIONS */ - -typedef struct _TransitionInfo TransitionInfo; -struct _TransitionInfo { - guint index; /* index into value arrays */ - gboolean pending; /* TRUE if we still need to handle it */ -}; - -static void -transition_info_add (TransitionInfo infos[GTK_CSS_PROPERTY_N_PROPERTIES], - GtkStyleProperty *property, - guint index) -{ - if (property == NULL) - { - guint i; - - for (i = 0; i < _gtk_css_style_property_get_n_properties (); i++) - { - GtkCssStyleProperty *prop = _gtk_css_style_property_lookup_by_id (i); - - transition_info_add (infos, GTK_STYLE_PROPERTY (prop), index); - } - } - else if (GTK_IS_CSS_SHORTHAND_PROPERTY (property)) - { - GtkCssShorthandProperty *shorthand = GTK_CSS_SHORTHAND_PROPERTY (property); - guint i; - - for (i = 0; i < _gtk_css_shorthand_property_get_n_subproperties (shorthand); i++) - { - GtkCssStyleProperty *prop = _gtk_css_shorthand_property_get_subproperty (shorthand, i); - - transition_info_add (infos, GTK_STYLE_PROPERTY (prop), index); - } - } - else if (GTK_IS_CSS_STYLE_PROPERTY (property)) - { - guint id; - - if (!_gtk_css_style_property_is_animated (GTK_CSS_STYLE_PROPERTY (property))) - return; - - id = _gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (property)); - g_assert (id < GTK_CSS_PROPERTY_N_PROPERTIES); - infos[id].index = index; - infos[id].pending = TRUE; - } - else - { - g_assert_not_reached (); - } -} - -static void -transition_infos_set (TransitionInfo infos[GTK_CSS_PROPERTY_N_PROPERTIES], - GtkCssValue *transitions) -{ - guint i; - - for (i = 0; i < _gtk_css_array_value_get_n_values (transitions); i++) - { - GtkStyleProperty *property; - GtkCssValue *prop_value; - - prop_value = _gtk_css_array_value_get_nth (transitions, i); - if (g_ascii_strcasecmp (_gtk_css_ident_value_get (prop_value), "all") == 0) - property = NULL; - else - { - property = _gtk_style_property_lookup (_gtk_css_ident_value_get (prop_value)); - if (property == NULL) - continue; - } - - transition_info_add (infos, property, i); - } -} - -static GtkStyleAnimation * -gtk_css_animated_values_find_transition (GtkCssAnimatedValues *values, - guint property_id) -{ - GSList *list; - - for (list = values->animations; list; list = list->next) - { - if (!GTK_IS_CSS_TRANSITION (list->data)) - continue; - - if (_gtk_css_transition_get_property (list->data) == property_id) - return list->data; - } - - return NULL; -} - -static void -gtk_css_animated_values_start_transitions (GtkCssAnimatedValues *values, - gint64 timestamp, - GtkCssComputedValues *source) -{ - TransitionInfo transitions[GTK_CSS_PROPERTY_N_PROPERTIES] = { { 0, } }; - GtkCssComputedValues *computed; - GtkCssValue *durations, *delays, *timing_functions; - guint i; - - computed = GTK_CSS_COMPUTED_VALUES (values); - - transition_infos_set (transitions, _gtk_css_computed_values_get_value (computed, GTK_CSS_PROPERTY_TRANSITION_PROPERTY)); - - durations = _gtk_css_computed_values_get_value (computed, GTK_CSS_PROPERTY_TRANSITION_DURATION); - delays = _gtk_css_computed_values_get_value (computed, GTK_CSS_PROPERTY_TRANSITION_DELAY); - timing_functions = _gtk_css_computed_values_get_value (computed, GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION); - - for (i = 0; i < GTK_CSS_PROPERTY_N_PROPERTIES; i++) - { - GtkStyleAnimation *animation; - GtkCssValue *start, *end; - double duration, delay; - - if (!transitions[i].pending) - continue; - - duration = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (durations, transitions[i].index), 100); - delay = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (delays, transitions[i].index), 100); - if (duration + delay == 0.0) - continue; - - start = _gtk_css_computed_values_get_intrinsic_value (source, i); - end = _gtk_css_computed_values_get_intrinsic_value (computed, i); - if (_gtk_css_value_equal (start, end)) - { - if (GTK_IS_CSS_ANIMATED_VALUES (source)) - { - animation = gtk_css_animated_values_find_transition (GTK_CSS_ANIMATED_VALUES (source), i); - if (animation) - values->animations = g_slist_prepend (values->animations, g_object_ref (animation)); - } - } - else - { - animation = _gtk_css_transition_new (i, - start, - end, - _gtk_css_array_value_get_nth (timing_functions, i), - timestamp + delay * G_USEC_PER_SEC, - timestamp + (delay + duration) * G_USEC_PER_SEC); - values->animations = g_slist_prepend (values->animations, animation); - } - } -} - -static GtkStyleAnimation * -gtk_css_animated_values_find_animation (GtkCssAnimatedValues *values, - const char *name) -{ - GSList *list; - - for (list = values->animations; list; list = list->next) - { - if (!GTK_IS_CSS_ANIMATION (list->data)) - continue; - - if (g_str_equal (_gtk_css_animation_get_name (list->data), name)) - return list->data; - } - - return NULL; -} - -static void -gtk_css_animated_values_start_css_animations (GtkCssAnimatedValues *values, - gint64 timestamp, - GtkStyleContext *context) -{ - GtkCssComputedValues *computed; - GtkStyleProviderPrivate *provider; - GtkCssValue *durations, *delays, *timing_functions, *animations; - GtkCssValue *iteration_counts, *directions, *play_states, *fill_modes; - guint i; - - computed = GTK_CSS_COMPUTED_VALUES (values); - - provider = _gtk_style_context_get_style_provider (context); - animations = _gtk_css_computed_values_get_value (computed, GTK_CSS_PROPERTY_ANIMATION_NAME); - durations = _gtk_css_computed_values_get_value (computed, GTK_CSS_PROPERTY_ANIMATION_DURATION); - delays = _gtk_css_computed_values_get_value (computed, GTK_CSS_PROPERTY_ANIMATION_DELAY); - timing_functions = _gtk_css_computed_values_get_value (computed, GTK_CSS_PROPERTY_ANIMATION_TIMING_FUNCTION); - iteration_counts = _gtk_css_computed_values_get_value (computed, GTK_CSS_PROPERTY_ANIMATION_ITERATION_COUNT); - directions = _gtk_css_computed_values_get_value (computed, GTK_CSS_PROPERTY_ANIMATION_DIRECTION); - play_states = _gtk_css_computed_values_get_value (computed, GTK_CSS_PROPERTY_ANIMATION_PLAY_STATE); - fill_modes = _gtk_css_computed_values_get_value (computed, GTK_CSS_PROPERTY_ANIMATION_FILL_MODE); - - for (i = 0; i < _gtk_css_array_value_get_n_values (animations); i++) - { - GtkStyleAnimation *animation; - GtkCssKeyframes *keyframes; - const char *name; - - name = _gtk_css_ident_value_get (_gtk_css_array_value_get_nth (animations, i)); - if (g_ascii_strcasecmp (name, "none") == 0) - continue; - - animation = gtk_css_animated_values_find_animation (values, name); - if (animation) - continue; - - keyframes = _gtk_style_provider_private_get_keyframes (provider, name); - if (keyframes == NULL) - continue; - - keyframes = _gtk_css_keyframes_compute (keyframes, context); - - animation = _gtk_css_animation_new (name, - keyframes, - timestamp + _gtk_css_number_value_get (_gtk_css_array_value_get_nth (delays, i), 100) * G_USEC_PER_SEC, - _gtk_css_number_value_get (_gtk_css_array_value_get_nth (durations, i), 100) * G_USEC_PER_SEC, - _gtk_css_array_value_get_nth (timing_functions, i), - _gtk_css_direction_value_get (_gtk_css_array_value_get_nth (directions, i)), - _gtk_css_play_state_value_get (_gtk_css_array_value_get_nth (play_states, i)), - _gtk_css_fill_mode_value_get (_gtk_css_array_value_get_nth (fill_modes, i)), - _gtk_css_number_value_get (_gtk_css_array_value_get_nth (iteration_counts, i), 100)); - values->animations = g_slist_prepend (values->animations, animation); - } -} - -/* PUBLIC API */ - -static void -gtk_css_animated_values_start_animations (GtkCssAnimatedValues *values, - gint64 timestamp, - GtkCssComputedValues *source, - GtkStyleContext *context) -{ - gtk_css_animated_values_start_transitions (values, timestamp, source); - gtk_css_animated_values_start_css_animations (values, timestamp, context); -} - -GtkCssComputedValues * -_gtk_css_animated_values_new (GtkCssComputedValues *computed, - GtkCssComputedValues *source, - gint64 timestamp, - GtkStyleContext *context) -{ - GtkCssAnimatedValues *values; - GtkCssValue *value; - GtkBitmask *ignore; - guint i; - - g_return_val_if_fail (GTK_IS_CSS_COMPUTED_VALUES (computed), NULL); - g_return_val_if_fail (GTK_IS_CSS_COMPUTED_VALUES (source), NULL); - g_return_val_if_fail (GTK_IS_STYLE_CONTEXT (context), NULL); - - values = g_object_new (GTK_TYPE_CSS_ANIMATED_VALUES, NULL); - - for (i = 0; ; i++) - { - value = _gtk_css_computed_values_get_value (computed, i); - - if (value == NULL) - break; - - _gtk_css_computed_values_set_value (GTK_CSS_COMPUTED_VALUES (values), - i, - value, - 0, - _gtk_css_computed_values_get_section (computed, i)); - } - - _gtk_bitmask_free (GTK_CSS_COMPUTED_VALUES (values)->depends_on_parent); - _gtk_bitmask_free (GTK_CSS_COMPUTED_VALUES (values)->equals_parent); - _gtk_bitmask_free (GTK_CSS_COMPUTED_VALUES (values)->depends_on_color); - _gtk_bitmask_free (GTK_CSS_COMPUTED_VALUES (values)->depends_on_font_size); - GTK_CSS_COMPUTED_VALUES (values)->depends_on_parent = _gtk_bitmask_copy (computed->depends_on_parent); - GTK_CSS_COMPUTED_VALUES (values)->equals_parent = _gtk_bitmask_copy (computed->equals_parent); - GTK_CSS_COMPUTED_VALUES (values)->depends_on_color = _gtk_bitmask_copy (computed->depends_on_color); - GTK_CSS_COMPUTED_VALUES (values)->depends_on_font_size = _gtk_bitmask_copy (computed->depends_on_font_size); - - gtk_css_animated_values_start_animations (values, timestamp, source, context); - - ignore = _gtk_css_animated_values_advance (values, timestamp); - _gtk_bitmask_free (ignore); - - return GTK_CSS_COMPUTED_VALUES (values); -} - -GtkBitmask * -_gtk_css_animated_values_advance (GtkCssAnimatedValues *values, - gint64 timestamp) -{ - GtkCssComputedValues *computed; - GtkBitmask *changed; - GPtrArray *old_animated_values; - GSList *list; - - g_return_val_if_fail (GTK_IS_CSS_ANIMATED_VALUES (values), NULL); - g_return_val_if_fail (timestamp >= values->current_time, NULL); - - computed = GTK_CSS_COMPUTED_VALUES (values); - changed = _gtk_bitmask_new (); - - values->current_time = timestamp; - old_animated_values = computed->animated_values; - computed->animated_values = NULL; - - list = values->animations; - while (list) - { - GtkStyleAnimation *animation = list->data; - - list = list->next; - - changed = _gtk_style_animation_set_values (animation, - changed, - timestamp, - GTK_CSS_COMPUTED_VALUES (values)); - - if (_gtk_style_animation_is_finished (animation, timestamp)) - { - values->animations = g_slist_remove (values->animations, animation); - g_object_unref (animation); - } - } - - if (old_animated_values) - g_ptr_array_unref (old_animated_values); - - return changed; -} - -gboolean -_gtk_css_animated_values_is_finished (GtkCssAnimatedValues *values) -{ - g_return_val_if_fail (GTK_IS_CSS_ANIMATED_VALUES (values), TRUE); - - return values->animations == NULL; -} diff --git a/gtk/gtkcssanimatedvaluesprivate.h b/gtk/gtkcssanimatedvaluesprivate.h deleted file mode 100644 index 65340f5d0c..0000000000 --- a/gtk/gtkcssanimatedvaluesprivate.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright © 2012 Red Hat Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library. If not, see . - * - * Authors: Benjamin Otte - */ - -#ifndef __GTK_CSS_ANIMATED_VALUES_PRIVATE_H__ -#define __GTK_CSS_ANIMATED_VALUES_PRIVATE_H__ - -#include "gtk/gtkcsscomputedvaluesprivate.h" - -G_BEGIN_DECLS - -#define GTK_TYPE_CSS_ANIMATED_VALUES (_gtk_css_animated_values_get_type ()) -#define GTK_CSS_ANIMATED_VALUES(obj) (G_TYPE_CHECK_INSTANCE_CAST (obj, GTK_TYPE_CSS_ANIMATED_VALUES, GtkCssAnimatedValues)) -#define GTK_CSS_ANIMATED_VALUES_CLASS(cls) (G_TYPE_CHECK_CLASS_CAST (cls, GTK_TYPE_CSS_ANIMATED_VALUES, GtkCssAnimatedValuesClass)) -#define GTK_IS_CSS_ANIMATED_VALUES(obj) (G_TYPE_CHECK_INSTANCE_TYPE (obj, GTK_TYPE_CSS_ANIMATED_VALUES)) -#define GTK_IS_CSS_ANIMATED_VALUES_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE (obj, GTK_TYPE_CSS_ANIMATED_VALUES)) -#define GTK_CSS_ANIMATED_VALUES_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_CSS_ANIMATED_VALUES, GtkCssAnimatedValuesClass)) - -typedef struct _GtkCssAnimatedValues GtkCssAnimatedValues; -typedef struct _GtkCssAnimatedValuesClass GtkCssAnimatedValuesClass; - -struct _GtkCssAnimatedValues -{ - GtkCssComputedValues parent; - - gint64 current_time; /* the current time in our world */ - GSList *animations; /* the running animations */ -}; - -struct _GtkCssAnimatedValuesClass -{ - GtkCssComputedValuesClass parent_class; -}; - -GType _gtk_css_animated_values_get_type (void) G_GNUC_CONST; - -GtkCssComputedValues * _gtk_css_animated_values_new (GtkCssComputedValues *computed, - GtkCssComputedValues *source, - gint64 timestamp, - GtkStyleContext *context); - -GtkBitmask * _gtk_css_animated_values_advance (GtkCssAnimatedValues *values, - gint64 timestamp) G_GNUC_WARN_UNUSED_RESULT; -gboolean _gtk_css_animated_values_is_finished (GtkCssAnimatedValues *values); - - -G_END_DECLS - -#endif /* __GTK_CSS_ANIMATED_VALUES_PRIVATE_H__ */ diff --git a/gtk/gtkcsscomputedvalues.c b/gtk/gtkcsscomputedvalues.c index ea44341ad9..1450068565 100644 --- a/gtk/gtkcsscomputedvalues.c +++ b/gtk/gtkcsscomputedvalues.c @@ -21,9 +21,20 @@ #include "gtkcsscomputedvaluesprivate.h" +#include "gtkcssanimationprivate.h" +#include "gtkcssarrayvalueprivate.h" +#include "gtkcssenumvalueprivate.h" #include "gtkcssinheritvalueprivate.h" #include "gtkcssinitialvalueprivate.h" +#include "gtkcssnumbervalueprivate.h" +#include "gtkcssshorthandpropertyprivate.h" +#include "gtkcssstringvalueprivate.h" #include "gtkcssstylepropertyprivate.h" +#include "gtkcsstransitionprivate.h" +#include "gtkstyleanimationprivate.h" +#include "gtkstylepropertiesprivate.h" +#include "gtkstylepropertyprivate.h" +#include "gtkstyleproviderprivate.h" G_DEFINE_TYPE (GtkCssComputedValues, _gtk_css_computed_values, G_TYPE_OBJECT) @@ -48,6 +59,9 @@ gtk_css_computed_values_dispose (GObject *object) values->animated_values = NULL; } + g_slist_free_full (values->animations, g_object_unref); + values->animations = NULL; + G_OBJECT_CLASS (_gtk_css_computed_values_parent_class)->dispose (object); } @@ -252,3 +266,295 @@ _gtk_css_computed_values_get_difference (GtkCssComputedValues *values, return result; } +/* TRANSITIONS */ + +typedef struct _TransitionInfo TransitionInfo; +struct _TransitionInfo { + guint index; /* index into value arrays */ + gboolean pending; /* TRUE if we still need to handle it */ +}; + +static void +transition_info_add (TransitionInfo infos[GTK_CSS_PROPERTY_N_PROPERTIES], + GtkStyleProperty *property, + guint index) +{ + if (property == NULL) + { + guint i; + + for (i = 0; i < _gtk_css_style_property_get_n_properties (); i++) + { + GtkCssStyleProperty *prop = _gtk_css_style_property_lookup_by_id (i); + + transition_info_add (infos, GTK_STYLE_PROPERTY (prop), index); + } + } + else if (GTK_IS_CSS_SHORTHAND_PROPERTY (property)) + { + GtkCssShorthandProperty *shorthand = GTK_CSS_SHORTHAND_PROPERTY (property); + guint i; + + for (i = 0; i < _gtk_css_shorthand_property_get_n_subproperties (shorthand); i++) + { + GtkCssStyleProperty *prop = _gtk_css_shorthand_property_get_subproperty (shorthand, i); + + transition_info_add (infos, GTK_STYLE_PROPERTY (prop), index); + } + } + else if (GTK_IS_CSS_STYLE_PROPERTY (property)) + { + guint id; + + if (!_gtk_css_style_property_is_animated (GTK_CSS_STYLE_PROPERTY (property))) + return; + + id = _gtk_css_style_property_get_id (GTK_CSS_STYLE_PROPERTY (property)); + g_assert (id < GTK_CSS_PROPERTY_N_PROPERTIES); + infos[id].index = index; + infos[id].pending = TRUE; + } + else + { + g_assert_not_reached (); + } +} + +static void +transition_infos_set (TransitionInfo infos[GTK_CSS_PROPERTY_N_PROPERTIES], + GtkCssValue *transitions) +{ + guint i; + + for (i = 0; i < _gtk_css_array_value_get_n_values (transitions); i++) + { + GtkStyleProperty *property; + GtkCssValue *prop_value; + + prop_value = _gtk_css_array_value_get_nth (transitions, i); + if (g_ascii_strcasecmp (_gtk_css_ident_value_get (prop_value), "all") == 0) + property = NULL; + else + { + property = _gtk_style_property_lookup (_gtk_css_ident_value_get (prop_value)); + if (property == NULL) + continue; + } + + transition_info_add (infos, property, i); + } +} + +static GtkStyleAnimation * +gtk_css_computed_values_find_transition (GtkCssComputedValues *values, + guint property_id) +{ + GSList *list; + + for (list = values->animations; list; list = list->next) + { + if (!GTK_IS_CSS_TRANSITION (list->data)) + continue; + + if (_gtk_css_transition_get_property (list->data) == property_id) + return list->data; + } + + return NULL; +} + +static void +gtk_css_computed_values_start_transitions (GtkCssComputedValues *values, + gint64 timestamp, + GtkCssComputedValues *source) +{ + TransitionInfo transitions[GTK_CSS_PROPERTY_N_PROPERTIES] = { { 0, } }; + GtkCssValue *durations, *delays, *timing_functions; + guint i; + + transition_infos_set (transitions, _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_TRANSITION_PROPERTY)); + + durations = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_TRANSITION_DURATION); + delays = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_TRANSITION_DELAY); + timing_functions = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_TRANSITION_TIMING_FUNCTION); + + for (i = 0; i < GTK_CSS_PROPERTY_N_PROPERTIES; i++) + { + GtkStyleAnimation *animation; + GtkCssValue *start, *end; + double duration, delay; + + if (!transitions[i].pending) + continue; + + duration = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (durations, transitions[i].index), 100); + delay = _gtk_css_number_value_get (_gtk_css_array_value_get_nth (delays, transitions[i].index), 100); + if (duration + delay == 0.0) + continue; + + start = _gtk_css_computed_values_get_intrinsic_value (source, i); + end = _gtk_css_computed_values_get_intrinsic_value (values, i); + if (_gtk_css_value_equal (start, end)) + { + animation = gtk_css_computed_values_find_transition (GTK_CSS_COMPUTED_VALUES (source), i); + if (animation) + values->animations = g_slist_prepend (values->animations, g_object_ref (animation)); + } + else + { + animation = _gtk_css_transition_new (i, + start, + end, + _gtk_css_array_value_get_nth (timing_functions, i), + timestamp + delay * G_USEC_PER_SEC, + timestamp + (delay + duration) * G_USEC_PER_SEC); + values->animations = g_slist_prepend (values->animations, animation); + } + } +} + +static GtkStyleAnimation * +gtk_css_computed_values_find_animation (GtkCssComputedValues *values, + const char *name) +{ + GSList *list; + + for (list = values->animations; list; list = list->next) + { + if (!GTK_IS_CSS_ANIMATION (list->data)) + continue; + + if (g_str_equal (_gtk_css_animation_get_name (list->data), name)) + return list->data; + } + + return NULL; +} + +static void +gtk_css_computed_values_start_css_animations (GtkCssComputedValues *values, + gint64 timestamp, + GtkStyleContext *context) +{ + GtkStyleProviderPrivate *provider; + GtkCssValue *durations, *delays, *timing_functions, *animations; + GtkCssValue *iteration_counts, *directions, *play_states, *fill_modes; + guint i; + + provider = _gtk_style_context_get_style_provider (context); + animations = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_NAME); + durations = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_DURATION); + delays = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_DELAY); + timing_functions = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_TIMING_FUNCTION); + iteration_counts = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_ITERATION_COUNT); + directions = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_DIRECTION); + play_states = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_PLAY_STATE); + fill_modes = _gtk_css_computed_values_get_value (values, GTK_CSS_PROPERTY_ANIMATION_FILL_MODE); + + for (i = 0; i < _gtk_css_array_value_get_n_values (animations); i++) + { + GtkStyleAnimation *animation; + GtkCssKeyframes *keyframes; + const char *name; + + name = _gtk_css_ident_value_get (_gtk_css_array_value_get_nth (animations, i)); + if (g_ascii_strcasecmp (name, "none") == 0) + continue; + + animation = gtk_css_computed_values_find_animation (values, name); + if (animation) + continue; + + keyframes = _gtk_style_provider_private_get_keyframes (provider, name); + if (keyframes == NULL) + continue; + + keyframes = _gtk_css_keyframes_compute (keyframes, context); + + animation = _gtk_css_animation_new (name, + keyframes, + timestamp + _gtk_css_number_value_get (_gtk_css_array_value_get_nth (delays, i), 100) * G_USEC_PER_SEC, + _gtk_css_number_value_get (_gtk_css_array_value_get_nth (durations, i), 100) * G_USEC_PER_SEC, + _gtk_css_array_value_get_nth (timing_functions, i), + _gtk_css_direction_value_get (_gtk_css_array_value_get_nth (directions, i)), + _gtk_css_play_state_value_get (_gtk_css_array_value_get_nth (play_states, i)), + _gtk_css_fill_mode_value_get (_gtk_css_array_value_get_nth (fill_modes, i)), + _gtk_css_number_value_get (_gtk_css_array_value_get_nth (iteration_counts, i), 100)); + values->animations = g_slist_prepend (values->animations, animation); + } +} + +/* PUBLIC API */ + +void +_gtk_css_computed_values_start_animations (GtkCssComputedValues *values, + gint64 timestamp, + GtkCssComputedValues *source, + GtkStyleContext *context) +{ + GtkBitmask *ignore; + + gtk_css_computed_values_start_transitions (values, timestamp, source); + gtk_css_computed_values_start_css_animations (values, timestamp, context); + + ignore = _gtk_css_computed_values_advance (values, timestamp); + _gtk_bitmask_free (ignore); +} + +GtkBitmask * +_gtk_css_computed_values_advance (GtkCssComputedValues *values, + gint64 timestamp) +{ + GtkBitmask *changed; + GPtrArray *old_computed_values; + GSList *list; + + g_return_val_if_fail (GTK_IS_CSS_COMPUTED_VALUES (values), NULL); + g_return_val_if_fail (timestamp >= values->current_time, NULL); + + changed = _gtk_bitmask_new (); + + values->current_time = timestamp; + old_computed_values = values->animated_values; + values->animated_values = NULL; + + list = values->animations; + while (list) + { + GtkStyleAnimation *animation = list->data; + + list = list->next; + + changed = _gtk_style_animation_set_values (animation, + changed, + timestamp, + GTK_CSS_COMPUTED_VALUES (values)); + + if (_gtk_style_animation_is_finished (animation, timestamp)) + { + values->animations = g_slist_remove (values->animations, animation); + g_object_unref (animation); + } + } + + if (old_computed_values) + g_ptr_array_unref (old_computed_values); + + return changed; +} + +gboolean +_gtk_css_computed_values_is_static (GtkCssComputedValues *values) +{ + GSList *list; + + g_return_val_if_fail (GTK_IS_CSS_COMPUTED_VALUES (values), TRUE); + + for (list = values->animations; list; list = list->next) + { + if (!_gtk_style_animation_is_static (list->data, values->current_time)) + return FALSE; + } + + return TRUE; +} diff --git a/gtk/gtkcsscomputedvaluesprivate.h b/gtk/gtkcsscomputedvaluesprivate.h index 1ddc4a776e..a79fc6c71f 100644 --- a/gtk/gtkcsscomputedvaluesprivate.h +++ b/gtk/gtkcsscomputedvaluesprivate.h @@ -43,13 +43,17 @@ struct _GtkCssComputedValues { GObject parent; - GPtrArray *values; - GPtrArray *sections; - GPtrArray *animated_values; - GtkBitmask *depends_on_parent; - GtkBitmask *equals_parent; - GtkBitmask *depends_on_color; - GtkBitmask *depends_on_font_size; + GPtrArray *values; /* the unanimated (aka intrinsic) values */ + GPtrArray *sections; /* sections the values are defined in */ + + GPtrArray *animated_values; /* NULL or array of animated values/NULL if not animated */ + gint64 current_time; /* the current time in our world */ + GSList *animations; /* the running animations, least important one first */ + + GtkBitmask *depends_on_parent; /* for intrinsic values */ + GtkBitmask *equals_parent; /* dito */ + GtkBitmask *depends_on_color; /* dito */ + GtkBitmask *depends_on_font_size; /* dito */ }; struct _GtkCssComputedValuesClass @@ -84,6 +88,13 @@ GtkCssValue * _gtk_css_computed_values_get_intrinsic_value (GtkCssCom GtkBitmask * _gtk_css_computed_values_get_difference (GtkCssComputedValues *values, GtkCssComputedValues *other); +void _gtk_css_computed_values_start_animations (GtkCssComputedValues *values, + gint64 timestamp, + GtkCssComputedValues *source, + GtkStyleContext *context); +GtkBitmask * _gtk_css_computed_values_advance (GtkCssComputedValues *values, + gint64 timestamp); +gboolean _gtk_css_computed_values_is_static (GtkCssComputedValues *values); G_END_DECLS diff --git a/gtk/gtkstylecontext.c b/gtk/gtkstylecontext.c index 227466219b..07cb1b4128 100644 --- a/gtk/gtkstylecontext.c +++ b/gtk/gtkstylecontext.c @@ -24,7 +24,6 @@ #include "gtkstylecontextprivate.h" #include "gtkcontainerprivate.h" -#include "gtkcssanimatedvaluesprivate.h" #include "gtkcssenginevalueprivate.h" #include "gtkcssnumbervalueprivate.h" #include "gtkcssrgbavalueprivate.h" @@ -526,7 +525,7 @@ style_data_unref (StyleData *data) static gboolean style_data_is_animating (StyleData *style_data) { - return GTK_IS_CSS_ANIMATED_VALUES (style_data->store); + return !_gtk_css_computed_values_is_static (style_data->store); } static GtkStyleInfo * @@ -3011,10 +3010,10 @@ gtk_style_context_update_animations (GtkStyleContext *context, style_data = style_data_lookup (context); - differences = _gtk_css_animated_values_advance (GTK_CSS_ANIMATED_VALUES (style_data->store), + differences = _gtk_css_computed_values_advance (style_data->store, timestamp); - if (_gtk_css_animated_values_is_finished (GTK_CSS_ANIMATED_VALUES (style_data->store))) + if (_gtk_css_computed_values_is_static (style_data->store)) _gtk_style_context_stop_animations (context); return differences; @@ -3043,32 +3042,27 @@ gtk_style_context_should_animate (GtkStyleContext *context) static void gtk_style_context_start_animations (GtkStyleContext *context, + GtkCssComputedValues *values, GtkCssComputedValues *previous, gint64 timestamp) { - StyleData *animated; - if (!gtk_style_context_should_animate (context)) { gtk_style_context_stop_animating (context); return; } - animated = style_data_new (); - animated->store = _gtk_css_animated_values_new (style_data_lookup (context)->store, - previous, - timestamp, - context); + _gtk_css_computed_values_start_animations (values, + timestamp, + previous, + context); - if (_gtk_css_animated_values_is_finished (GTK_CSS_ANIMATED_VALUES (animated->store))) + if (_gtk_css_computed_values_is_static (values)) { - style_data_unref (animated); gtk_style_context_stop_animating (context); return; } - style_info_set_data (context->priv->info, animated); - style_data_unref (animated); gtk_style_context_start_animating (context); } @@ -3172,11 +3166,11 @@ _gtk_style_context_validate (GtkStyleContext *context, { StyleData *data; - gtk_style_context_start_animations (context, current->store, timestamp); - change &= ~GTK_CSS_CHANGE_ANIMATE; - data = style_data_lookup (context); + gtk_style_context_start_animations (context, data->store, current->store, timestamp); + change &= ~GTK_CSS_CHANGE_ANIMATE; + changes = _gtk_css_computed_values_get_difference (data->store, current->store); } else -- 2.30.2